* Some functions
#+BEGIN_SRC lua
   function os.capture(cmd, raw)
     local f = assert(io.popen(cmd, 'r'))
     local s = assert(f:read('*a'))
     f:close()
     if raw then return s end
     s = string.gsub(s, '^%s+', '')
     s = string.gsub(s, '%s+$', '')
     s = string.gsub(s, '[\n\r]+', ' ')
     return s
   end
   function split(s, delimiter)
     result = {};
     for match in (s..delimiter):gmatch("(.-)"..delimiter) do
         table.insert(result, match);
     end
     return result;
   end
#+END_SRC
* Requires
Basic awesome modules
#+BEGIN_SRC lua
  local gears = require("gears")
  local awful = require("awful")
  local wibox = require("wibox")
  local beautiful = require("beautiful")
  local naughty = require("naughty")
  require("awful.autofocus")

  gears.debug.print_error = function(message)
    naughty.notify({text = message})
  end
#+END_SRC

* Theme
#+BEGIN_SRC lua
  beautiful.init({
      useless_gap = 12,
      gaps = {12, 32, 64, 0},
      bg_normal = "#^color-bg^",      
      titlebar_size = 30,
      titlebar_fg_normal = "#^color-bg-light2^",
      titlebar_bg_normal = "#^color-bg^",
      titlebar_fg_focus = "#^color-fg^",
      titlebar_bg_focus = "#^color-bg-light^",
      font = "Hack 9",
      corner_radius = 5,
      wibar_height = 30,
      wibar_bg = "#^color-bg^",
      wibar_position = "bottom"
  })
  root.cursor("cursor")
#+END_SRC
* Screen setup
** Put all screens in a table
Also set primary screen
#+BEGIN_SRC lua
  local screens = {}

  awful.screen.connect_for_each_screen(function(s)
      screens = gears.table.join(screens, {s})
  end)

  if #screens == 2 then
    screens = {screens[2], screens[1]}
  end

  local primary_screen = screens[1]

  local current_screen = primary_screen

#+END_SRC
** Layouts
#+BEGIN_SRC lua
  awful.layout.layouts = {
    awful.layout.suit.tile
  }
#+END_SRC   
** Setup tags for each screen
#+BEGIN_SRC lua
  local tags = {}
  local tag = {
    names = {"1", "2", "3", "4", "5", "6", "7", "8", "9"},
    per = 3
  }
  
  for i = 1, #screens do
    tempTagNames = {}
    for e = i * (tag.per - 1), i * (tag.per - 1) + (tag.per - 1) do
      tempTagNames = gears.table.join(tempTagNames, {tag.names[e]})
    end
    tags = gears.table.join(tags, awful.tag.new(tempTagNames, screens[i], awful.layout.layouts[1]))
  end
#+END_SRC
* Functions
Toggles gaps on current tag
#+BEGIN_SRC lua
  function toggleGaps()
    tag = awful.screen.focused().selected_tag
    next = 1
    for i = 1, #beautiful.gaps do
      if beautiful.gaps[i] == tag.gap then
        next = i + 1
        break
      end
    end
    if #beautiful.gaps < next then
      next = 1
    end
    tag.gap = beautiful.gaps[next]
    awful.layout.arrange(awful.screen.focused())
  end
#+END_SRC
Toggle languages
#+BEGIN_SRC lua
  local currentKbd = "us"
  local kbds = {"us", "sk qwerty", "de qwerty"}

  function toggleKbd()
    local next = 1
    for i = 1, #kbds do
      if kbds[i] == currentKbd then
        next = i + 1
        break
      end
    end
    if next > #kbds then
      next = 1
    end
    currentKbd = kbds[next]
    awful.spawn("setxkbmap " .. currentKbd)
    keyboardModuleUpdate()
  end
#+END_SRC

* Program Names
#+BEGIN_SRC lua
  local hDIR = os.getenv("HOME")
  local prog = {
    terminal = "xst",
    launcher = "bash " .. hDIR .. "/.scripts/menu.bash " .. hDIR .. "/.config/menus/programs",
    util = "bash " .. hDIR .. "/.scripts/menu.bash " .. hDIR .. "/.config/menus/util"    
  }
#+END_SRC
* Titlebars
#+BEGIN_SRC lua
  client.connect_signal("request::titlebars", function(c)
        awful.titlebar(c, {size = beautiful.titlebar_size, font = beautiful.font}) : setup {
          nil,
          {
            {
              align = "center",
              widget = awful.titlebar.widget.titlewidget(c)
            },
            layout = wibox.layout.flex.horizontal
          },
          nil,
          layout = wibox.layout.align.horizontal
                               }
  end)
#+END_SRC
* Wibar
** Widgets
#+BEGIN_SRC lua
  local wibar = {}
  wibar.left = {}
  wibar.middle = {}
  wibar.right = {}

  local wimods = {}
#+END_SRC
** Taglist
#+BEGIN_SRC lua
  local tagModule = {}

  tagModule.size = {14,14}
  tagModule.tsize = {beautiful.wibar_height, beautiful.wibar_height}
  tagModule.pos = {(tagModule.tsize[1] - tagModule.size[1]) / 2, (tagModule.tsize[2] - tagModule.size[2]) / 2}

  tagModule.surfaces = {
    focused = gears.surface.load_from_shape(tagModule.tsize[1],tagModule.tsize[2],gears.shape.rectangle,"#^color-fg^"),
    normal = gears.surface.load_from_shape(tagModule.tsize[1],tagModule.tsize[2],gears.shape.rectangle,"#^color-bg-light^"),
    occupied = gears.surface.load_from_shape(tagModule.tsize[1],tagModule.tsize[2],gears.shape.rectangle,"#^color-bg-light3^")    
  }

  function tagModule.shape(cr, width, height)
    return gears.shape.transform(gears.shape.rounded_bar) : translate(tagModule.pos[1], tagModule.pos[2]) (cr, tagModule.size[1], tagModule.size[2])
  end

  tagModule.list = {}

  for i = 1, #tags do
    tagModule.list = gears.table.join(tagModule.list, {
                                 wibox.widget.imagebox(
                                   tagModule.surfaces.normal,
                                   false,
                                   tagModule.shape
                                 )
                                        }
    )
    tagModule.list[#tagModule.list].forced_width = tagModule.tsize[1]
    tagModule.list[#tagModule.list].forced_height = tagModule.tsize[2]  
  end

  tagModule.widget = wibox.widget(
    gears.table.join({layout = wibox.layout.flex.horizontal}, tagModule.list)
  )

  function tagModuleUpdate()
    for i = 1, #tagModule.list do
      if tags[i].selected then
        tagModule.list[i].image = tagModule.surfaces.focused
      elseif #tags[i]:clients() > 0 then
        tagModule.list[i].image = tagModule.surfaces.occupied
      else
        tagModule.list[i].image = tagModule.surfaces.normal
      end
    end
  end
#+END_SRC
** Volume indicator
#+BEGIN_SRC lua
  local volumeModule = {}
  volumeModule.tsize = {150, beautiful.wibar_height}
  volumeModule.size = {150 - 20, 14}
  volumeModule.pos = {(volumeModule.tsize[1] - volumeModule.size[1]) / 2, (volumeModule.tsize[2] - volumeModule.size[2]) / 2}
  volumeModule.surfaces = {
      active = gears.surface.load_from_shape(volumeModule.tsize[1], volumeModule.tsize[2], gears.shape.rectangle,"#^color-fg^"),
      activeMute = gears.surface.load_from_shape(volumeModule.tsize[1], volumeModule.tsize[2], gears.shape.rectangle,"#^color-bg-light2^"),
      overMute = gears.surface.load_from_shape(volumeModule.tsize[1], volumeModule.tsize[2], gears.shape.rectangle,"#^color-bg-light3^"),    
      over = gears.surface.load_from_shape(volumeModule.tsize[1], volumeModule.tsize[2], gears.shape.rectangle,"#^color-red^"),      
      background = gears.surface.load_from_shape(volumeModule.tsize[1], volumeModule.tsize[2], gears.shape.rectangle,"#^color-bg-light^")
  }

  volumeModule.perc = 0
  volumeModule.overPerc = 0
  volumeModule.mute = 0

  volumeModule.shapes = {}

  function volumeModule.shapes.active(cr, w, h)
    return gears.shape.transform(gears.shape.rounded_bar) : translate(volumeModule.pos[1] + ((1 - volumeModule.perc) / 2) * volumeModule.size[1] or 0, volumeModule.pos[2]) (cr, volumeModule.perc * volumeModule.size[1], volumeModule.size[2])
  end

  function volumeModule.shapes.over(cr, w, h)  
    return gears.shape.transform(gears.shape.rounded_bar) : translate(volumeModule.pos[1] + ((1 - volumeModule.overPerc) / 2) * volumeModule.size[1] or 0, volumeModule.pos[2]) (cr, volumeModule.overPerc * volumeModule.size[1], volumeModule.size[2])
  end

  function volumeModule.shapes.background(cr, w, h)
    return gears.shape.transform(gears.shape.rounded_bar) : translate(volumeModule.pos[1], volumeModule.pos[2]) (cr, volumeModule.size[1], volumeModule.size[2])
  end

  volumeModule.widgets = {}

  volumeModule.widgets.active = wibox.widget.imagebox(
    volumeModule.surfaces.activeMute,
    false,
    volumeModule.shapes.active
  )

  volumeModule.widgets.background = wibox.widget.imagebox(
    volumeModule.surfaces.background,
    false,
    volumeModule.shapes.background
  )

  volumeModule.widgets.over = wibox.widget.imagebox(
    volumeModule.surfaces.overMute,
    false,
    volumeModule.shapes.over
  )

  volumeModule.widget = wibox.widget {
    volumeModule.widgets.background,
    volumeModule.widgets.active,
    volumeModule.widgets.over,
    layout = wibox.layout.stack
  }

  function volumeModuleUpdate()
    if volumeModule.lockUpdate then
      return
    end
    local vol = tonumber(gears.string.split(os.capture("pulsemixer --get-volume"), " ")[1])
    local mute = tonumber(os.capture("pulsemixer --get-mute"))

    if vol > 100 then
      if volumeModule.overPerc == (vol - 100) / 100 and mute == volumeModule.mute then
        return
      end
      volumeModule.overPerc = (vol - 100) / 100
      volumeModule.perc = 1
    else
      if volumeModule.perc == vol / 100 and mute == volumeModule.mute then
        return
      end
      volumeModule.overPerc = 0
      volumeModule.perc = vol / 100
    end

    if mute == 1 then
      volumeModule.widgets.active.image = volumeModule.surfaces.activeMute
      volumeModule.widgets.over.image = volumeModule.surfaces.overMute
    elseif mute == 0 then
      volumeModule.widgets.active.image = volumeModule.surfaces.active
      volumeModule.widgets.over.image = volumeModule.surfaces.over
    end

    volumeModule.mute = mute

    volumeModule.widgets.active:emit_signal("widget::redraw_needed")
    volumeModule.widgets.over:emit_signal("widget::redraw_needed")
    volumeModule.lockUpdate = true
    volumeModule.lockTimer = gears.timer {
      timeout = 0.1,
      autostart = true,
      callback = function()
        volumeModule.lockUpdate = false
        volumeModule.lockTimer:stop()
      end
    }
  end

  volumeModuleUpdate()
#+END_SRC
** Internet indicator
#+BEGIN_SRC lua
  local internetModule = {}

  internetModule.tsize = {beautiful.wibar_height, beautiful.wibar_height}
  internetModule.size = {14,14}

  internetModule.piePos = {
    (internetModule.tsize[1] - 2 * internetModule.size[1]) / 2,
    (internetModule.tsize[2] - 2 * internetModule.size[2]) / 2 + internetModule.size[2] / 2
  }

  internetModule.cirPos = {
    (internetModule.tsize[1] - internetModule.size[1]) / 2,
    (internetModule.tsize[2] - internetModule.size[2]) / 2
  }

  internetModule.crossPos = {
    (math.sqrt(math.pow(internetModule.tsize[1], 2) + math.pow(internetModule.tsize[2], 2)) - math.sqrt(math.pow(internetModule.size[1], 2) + math.pow(internetModule.size[2], 2))) / 2,
    0
  }

  internetModule.radius = 14

  internetModule.shapes = {
    pie = {},
    cir = {},
    cross = {}
  }

  internetModule.name = "test"
  internetModule.isWifi = false
  internetModule.wifiQuality = 0
  internetModule.isConnected = false

  function internetModule.shapes.pie.active(cr, w, h)
    return gears.shape.transform(gears.shape.pie) : translate(internetModule.piePos[1], internetModule.piePos[2]) (cr, internetModule.size[1] * 2, internetModule.size[2] * 2, math.pi * 1.25, math.pi * 1.75, internetModule.radius * internetModule.wifiQuality)
  end

  function internetModule.shapes.pie.background(cr, w, h)
    return gears.shape.transform(gears.shape.pie) : translate(internetModule.piePos[1], internetModule.piePos[2]) (cr, internetModule.size[1] * 2, internetModule.size[2] * 2, math.pi * 1.25, math.pi * 1.75, internetModule.radius)
  end

  function internetModule.shapes.cir.active(cr, w, h)
    return gears.shape.transform(gears.shape.circle) : translate(internetModule.cirPos[1], internetModule.cirPos[2]) (cr, internetModule.size[1], internetModule.size[2])
  end

  function internetModule.shapes.cross.active(cr, w, h)
    return gears.shape.transform(gears.shape.cross) : rotate(math.pi / 4) : translate(internetModule.crossPos[1], internetModule.crossPos[2]) (cr, internetModule.size[1], internetModule.size[2])
  end

  internetModule.surfaces = {
    active = gears.surface.load_from_shape(internetModule.tsize[1], internetModule.tsize[2], gears.shape.rectangle,"#^color-fg^"),
    background = gears.surface.load_from_shape(internetModule.tsize[1], internetModule.tsize[2], gears.shape.rectangle,"#^color-bg-light^")

  }

  internetModule.widgets = {}

  internetModule.widgets.foreground = wibox.widget.imagebox(
    internetModule.surfaces.background,
    false,
    internetModule.shapes.cir.active
  )

  internetModule.widgets.background = wibox.widget.imagebox(
    internetModule.surfaces.background,
    false,
    internetModule.shapes.cir.active
  )

  internetModule.widget = wibox.widget {
    internetModule.widgets.background,
    internetModule.widgets.foreground,
    layout = wibox.layout.stack
  }

  function internetModuleUpdate()
    local name = internetModule.name
    local isWifi = internetModule.isWifi
    local signal = internetModule.wifiQuality
    local isConnected = internetModule.isConnected

    local i = 0
    for line in io.lines(hDIR .. "/tmp/internetInfo") do
      i = i + 1
      if i == 1 then
        name = line
      elseif i == 2 then
        isWifi = line == "1"
      elseif i == 3 then
        signal = tonumber(line) / 100
      else
        isConnected = line == "1"
      end
    end

    local isChange = false
    if not isWifi == internetModule.isWifi then
      if isWifi then
        internetModule.widgets.foreground.clip_shape = internetModule.shapes.pie.active
        internetModule.widgets.background.clip_shape = internetModule.shapes.pie.background
      else
        internetModule.widgets.foreground.clip_shape = internetModule.shapes.cir.active
        internetModule.widgets.background.clip_shape = internetModule.shapes.cir.active
      end
      isChange = true
    end

    if not isConnected == internetModule.isConnected then
      if isConnected then
        internetModule.widgets.foreground.image = internetModule.surfaces.active
      else
        internetModule.widgets.foreground.image = internetModule.surfaces.background
        internetModule.widgets.foreground.clip_shape = internetModule.shapes.cir.active
        internetModule.widgets.background.clip_shape = internetModule.shapes.cir.active
      end
      isChange = true
    end

    if not signal == internetModule.wifiQuality then
      isChange = true
    end

    internetModule.isWifi = isWifi
    internetModule.wifiQuality = signal
    internetModule.isConnected = isConnected

    if isChange then
      internetModule.widgets.foreground:emit_signal("widget::redraw_needed")
      internetModule.widgets.background:emit_signal("widget::redraw_needed")
    end
  end


  gears.timer {
    timeout = 8,
    autostart = true,
    call_now = true,
    callback = function()
      awful.spawn.with_shell("bash " .. hDIR .. "/.scripts/internetInfo.bash")
      internetModuleUpdate()
    end
  }
#+END_SRC
** Battery
#+BEGIN_SRC lua
  local batteryModule = {}
  batteryModule.tsize = {beautiful.wibar_height, beautiful.wibar_height}
  batteryModule.size = {
    14,
    14
  }

  batteryModule.pos = {
    (batteryModule.tsize[1] - batteryModule.size[1]) / 2,
    (batteryModule.tsize[2] - batteryModule.size[2]) / 2  
  }

  batteryModule.surfaces = {
    active = gears.surface.load_from_shape(batteryModule.tsize[1], batteryModule.tsize[2], gears.shape.rectangle, "#^color-fg^")
  }

  batteryModule.perc = 1
  batteryModule.shapes = {}

  batteryModule.shapes.foreground = function(cr, w, h)
    return gears.shape.transform(gears.shape.arc) : translate(batteryModule.pos[1], batteryModule.pos[2]) (cr, batteryModule.size[1], batteryModule.size[2], 3,-math.pi / 2, 2 * math.pi * batteryModule.perc - math.pi / 2, true, true)
  end

  batteryModule.shapes.background = function(cr, w, h)
    return gears.shape.transform(gears.shape.circle) : translate(batteryModule.pos[1], batteryModule.pos[2]) (cr, batteryModule.size[1], batteryModule.size[2])
  end

  batteryModule.widgets = {}
  batteryModule.widgets.foreground = wibox.widget.imagebox(
    batteryModule.surfaces.active,
    false,
    batteryModule.shapes.foreground
  )

  batteryModule.widgets.textbox = wibox.widget.textbox()


  batteryModule.widget = wibox.widget {
    batteryModule.widgets.foreground,
    batteryModule.widgets.textbox,
    layout = wibox.layout.fixed.horizontal
  }

  function batteryModuleUpdate()
    local perc = tonumber(os.capture("bash " .. hDIR .. "/.scripts/batteryPerc.bash")) / 100
    if perc ~= batteryModule.perc then
      batteryModule.perc = perc
      batteryModule.widgets.foreground:emit_signal("widget::redraw_needed")
    end
    batteryModule.widgets.textbox.markup = tostring(math.floor(batteryModule.perc * 100 + 0.5)) .. "%"

  end

  function getBatteryWidget()
    if os.capture("bash " .. hDIR .. "/.scripts/batteryPerc.bash") ~= "noBattery" then
      gears.timer {
        timeout = 10,
        autostart = true,
        call_now = true,
        callback = function()
          batteryModuleUpdate()
        end
      }
      return batteryModule.widget
    end
  end
#+END_SRC
** Keyboard Layout
#+BEGIN_SRC lua
  local keyboardModule = {}

  keyboardModule.widgets = {}
  keyboardModule.widgets.textbox = wibox.widget.textbox()

  keyboardModule.widget = wibox.widget {
    keyboardModule.widgets.textbox,
    layout = wibox.layout.stack
  }

  keyboardModule.widget:connect_signal("button::press", toggleKbd)

  function keyboardModuleUpdate()
    keyboardModule.widgets.textbox.markup = gears.string.split(currentKbd, " ")[1]:upper()
  end

  keyboardModuleUpdate()
#+END_SRC
** Setup
#+BEGIN_SRC lua
  local wibar = awful.wibar({ screen = primary_screen, position = beautiful.wibar_position })
  wibar:setup {
    layout = wibox.layout.align.horizontal,
    {
      layout = wibox.layout.fixed.horizontal,
      tagModule.widget
    },
    nil,
    {
      layout = wibox.layout.fixed.horizontal,
      keyboardModule.widget,
      getBatteryWidget(),
      internetModule.widget,
      wibox.widget.textclock()
    },
  }
  tagModuleUpdate()
#+END_SRC
* Vertical Menu
#+BEGIN_SRC lua
    function wrap(x, min, max)
      if x < min then
        return max
      elseif x > max then
        return min
      end
      return x
    end

    local VerticalMenu = {}

    function VerticalMenu:new()
      local ins = {}
      setmetatable(ins, self)
      self.__index = self
      return ins
    end

    function VerticalMenu:create(args)

      self.screen = args.screen
      self.elements = args.elements
      self.size = {
        args.size,
        args.size * #self.elements
      }

      self.pos = {
        self.screen.geometry.x + args.offset,
        self.screen.geometry.y + (self.screen.geometry.height - (beautiful.wibar_height + self.size[2])) / 2
      }
    
      if args.side == "right" then
        self.pos[1] = (self.screen.geometry.x + self.screen.geometry.width) - (self.size[1] + args.offset)
      end

      self.bg = args.bg or beautiful.bg_normal or "#000000"
      self.focusBg = args.focusBg or beautiful.bg_focus or "#404040"
      self.radius = args.radius or beautiful.corner_radius or 0
      self.margin = args.margin or 10
      self.widgets = {}
      self.widget = nil

      self.selectedIndex = 1

      self.keyGrabber = awful.keygrabber {
        keybindings = {
          {{"Control"}, "n", function()
              self.selectedIndex = wrap(self.selectedIndex + 1, 1, #self.widgets)
              self:update()
          end},
          {{"Control"}, "p", function()
              self.selectedIndex = wrap(self.selectedIndex - 1, 1, #self.widgets)
              self:update()
          end},
          {{"Mod1"}, "q", function()
              self.keyGrabber:stop()
              self:toggle()
          end},
          {{"Mod4"}, "q", function()
              self.keyGrabber:stop()
              self:toggle()
          end},
          {{"Mod4"}, "g", function()
              self.keyGrabber:stop()
              self:toggle()
          end},
          {{}, "Escape", function()
              self.keyGrabber:stop()
              self:toggle()
          end},
          {{}, "Return", function()
              self.keyGrabber:stop()
              self:toggle()
              self.elements[self.selectedIndex].callback()
          end},
          {{"Control"}, "m", function()
              self.keyGrabber:stop()
              self:toggle()
              self.elements[self.selectedIndex].callback()
          end}

        }
      }
      self:createWidgets()

      self.wibox = wibox({
          x = self.pos[1],
          y = self.pos[2],
          width = self.size[1],
          height = self.size[2],
          visible = false,
          ontop = true,
          widget = self.widget,
          bg = self.bg,
          shape = function(cr, w, h)
            return self:shape(cr, w, h)
          end
      })

      return self
    end

    function VerticalMenu:toggle()
      self.wibox.visible = not self.wibox.visible
      if self.wibox.visible then
        self.keyGrabber:start()
        self.selectedIndex = 1
        self:update()
      else
        self.keyGrabber:stop()
      end
    end

    function VerticalMenu:update()
      for i = 1, #self.widgets do
        if i == self.selectedIndex then
          self.widgets[i].bg = self.focusBg
        else
          self.widgets[i].bg = self.bg
        end
      end
    end

    function VerticalMenu:shape(cr, w, h)
      return gears.shape.rounded_rect(cr, w, h, self.radius)
    end

    function VerticalMenu:createWidgets()
      for i = 1, #self.elements do
        local bg = self.bg
        local widget
        local containedWidget    
        if self.elements[i].image then
          widget = wibox.widget.imagebox(self.elements[i].image)
          containedWidget = wibox.container.background(wibox.container.margin(widget, self.margin, self.margin, self.margin, self.margin), bg)      
        else
          widget = wibox.widget.textbox(self.elements[i].text)
          containedWidget = wibox.container.background(wibox.container.place(widget), bg)
        end

        self.widgets = gears.table.join(self.widgets, {containedWidget})
      end
      self.widget = wibox.widget(
        gears.table.join(self.widgets, {layout = wibox.layout.flex.vertical})
      )
      self:update()
    end

    function VerticalMenu:makeImageShape()
      local size = {self.size[1] - self.margin * 2, (self.size[2] / #self.elements) - self.margin * 2}
      local pos = {self.margin, self.margin}
      return function(cr, w, h)
        return gears.shape.transform(gears.shape.rectangle) (cr, size[1], size[2])
      end
    end
#+END_SRC
* Vertical Slider
#+BEGIN_SRC lua
  local VerticalSlider = {}

  function VerticalSlider:new()
    local ins = {}
    setmetatable(ins, self)
    self.__index = self
    return ins
  end

  function VerticalSlider:create(args)
    self.screen = args.screen
    self.elements = args.elements
    self.size = {
      args.size,
      args.size * 4
    }

    self.pos = {
      self.screen.geometry.x + args.offset,
      self.screen.geometry.y + (self.screen.geometry.height - (beautiful.wibar_height + self.size[2])) / 2
    }

    if args.side == "right" then
      self.pos[1] = (self.screen.geometry.x + self.screen.geometry.width) - (self.size[1] + args.offset)
    end

    self.margin = args.margin or 20

    self.handleSize = {
      (self.size[1] - self.margin) / 2, (self.size[1] - self.margin) / 2
    }



    self.bg = args.bg or beautiful.bg_normal or "#000000"
    self.fg = args.fg or beautiful.bg_focus or "#FFFFFF"
    self.focusBg = args.focusBg or beautiful.bg_focus or "#404040"
    self.radius = args.radius or beautiful.corner_radius or 0
    self.widgets = {}
    self.widget = nil
    self.slider = nil
    self.mouseInside = false

    self.recentlyUpdated = false
    self.callback = args.callback

    self:createWidgets()

    self.slider:connect_signal("property::value", function()
                                 if not self.recentlyUpdated then
                                   self.callback(self.slider.value)
                                 else
                                   self.recentlyUpdated = false
                                 end
    end)

    self.wibox = wibox({
        x = self.pos[1],
        y = self.pos[2],
        width = self.size[1],
        height = self.size[2],
        visible = false,
        ontop = true,
        widget = self.widget,
        bg = self.bg,
        shape = function(cr, w, h)
          return self:shape(cr, w, h)
        end
    })

    return self

  end

  function VerticalSlider:toggle()
    self.wibox.visible = not self.wibox.visible
  end

  function VerticalSlider:shape(cr, w, h)
    return gears.shape.rounded_rect(cr, w, h, self.radius)
  end

  function VerticalSlider:createWidgets()
    local slider = wibox.widget({
        bar_shape           = gears.shape.rounded_bar,
        bar_height          = 3,
        bar_color           = self.focusBg,
        handle_color        = self.fg,
        handle_shape        = gears.shape.circle,
        handle_border_width = 0,
        value               = 25,
        widget = wibox.widget.slider
    })

    self.slider = slider

    local containedWidget = wibox.container.margin(wibox.container.rotate(slider, "east"), self.margin, self.margin, self.margin, self.margin)

    self.widgets = {containedWidget}
    self.widget = wibox.widget(
      gears.table.join(self.widgets, {layout = wibox.layout.flex.vertical})
    )
  end

  function VerticalSlider:update(val)
    self.recentlyUpdated = true
    self.slider.value = val
  end
#+END_SRC
* Power Menu
#+BEGIN_SRC lua
  local powerMenu = VerticalMenu:new():create({
      screen = primary_screen,
      size = 100,
      offset = 10,
      margin = 35,
      side = "right",
      elements = {
        {text = "Power Off", image = "/home/anon/.icons/poweroff.png", callback = function() awful.spawn.with_shell("poweroff") end},
        {text = "Reboot", image = "/home/anon/.icons/reboot.png", callback = function() awful.spawn.with_shell("reboot") end},
        {text = "Suspend", image = "/home/anon/.icons/suspend.png", callback = function() awful.spawn.with_shell("systemctl suspend") end}
      }

                                            })
#+END_SRC
* Volume Slider
#+BEGIN_SRC lua

  local volumeSlider = VerticalSlider:new():create({
      screen = primary_screen,
      offset = 10,
      size = 80,
      margin = 20,
      side = "left",
      callback = function(val)
      end
                                                  })
  volumeSlider.isMuted = false

  function volumeSlider:refresh()
    self.volume = tonumber(gears.string.split(os.capture("pulsemixer --get-volume"), " ")[1])
    self.isMuted = tonumber(os.capture("pulsemixer --get-mute")) == 1
    if self.isMuted then
      self.slider.handle_color = self.focusBg
    else
      self.slider.handle_color = self.fg
    end
    self:update(math.floor((self.volume / 150) * 100 + 0.5))
  end

  function volumeSlider:updateExternal()
    self.volume = math.floor(((self.slider.value / 100) * 150) + 0.5)
    awful.spawn.with_shell("pulsemixer --set-volume " .. tostring(self.volume))
  end

  function volumeSlider:show()
    self.wibox.visible = true
    self.timer:again()
  end

  function volumeSlider:hide()
    self.wibox.visible = false
  end

  volumeSlider.slider:connect_signal("property::value", function()
                                       if not volumeSlider.recentlyUpdated then
                                         volumeSlider.timer:again()
                                         volumeSlider.updateTimer:again()
                                       end
  end)

  volumeSlider.timer = gears.timer({
      timeout = 3,
      single_shot = true,
      callback = function()
        volumeSlider:hide()
      end
  })

  volumeSlider.updateTimer = gears.timer({
      timeout = 0.1,
      single_shot = true,
      callback = function()
        volumeSlider:updateExternal()
      end
  })
#+END_SRC
* Search menu
#+BEGIN_SRC lua
  local SearchMenu = {}

  function SearchMenu:new()
    local ins = {}
    setmetatable(ins, self)
    self.__index = self
    return ins
  end

  function SearchMenu:create(args)
    self.screen = args.screen
    self.size = {
      args.width,
      args.height
    }
    self.pos = {
      0,0
    }

    self.bg = args.bg or beautiful.bg_normal or "#000000"
    self.focusBg = args.focusBg or beautiful.bg_focus or "#404040"

    self.widgets = {}
    self.widget = nil

  
  end
#+END_SRC
* Keys
** Modkeys
#+BEGIN_SRC lua
  key = {
    mod = "Mod4",
    alt = "Mod1",
    ctrl = "Control",
    shift = "Shift"
  }
#+END_SRC
** Keybindings
Keys and buttons table
#+BEGIN_SRC lua
  keys = {}
  buttons = {}
#+END_SRC
Global keys
#+BEGIN_SRC lua
  keys.global = gears.table.join(
    awful.key({key.mod}, "d", function() awful.spawn(prog.launcher) end),
    awful.key({key.mod}, "x", function() awful.spawn(prog.util) end),    
    awful.key({key.mod}, "Return", function() awful.spawn(prog.terminal) end),
    awful.key({key.mod, key.shift}, "r", awesome.restart),
    awful.key({key.mod}, "p", function() awful.client.focus.global_bydirection("up") end),
    awful.key({key.mod}, "n", function() awful.client.focus.global_bydirection("down") end),
    awful.key({key.mod}, "b", function() awful.client.focus.global_bydirection("left") end),
    awful.key({key.mod}, "o", function() awful.client.focus.global_bydirection("right") end),
    awful.key({key.mod}, "g", toggleGaps),
    awful.key({key.mod}, "t", toggleKbd),
    awful.key({key.mod}, "q", function() powerMenu:toggle() end),
    awful.key({key.mod}, "w", function() volumeSlider:toggle() end),
    awful.key({key.mod}, "m", function() awful.spawn.with_shell("pulsemixer --toggle-mute") volumeSlider:refresh() volumeSlider:show() end),
    awful.key({key.mod}, "v", function() awful.spawn.with_shell("pulsemixer --change-volume -5") volumeSlider:refresh() volumeSlider:show() end),
    awful.key({key.mod, key.shift}, "v", function() awful.spawn.with_shell("pulsemixer --change-volume +5") volumeSlider:refresh() volumeSlider:show() end),    
    awful.key({key.mod, key.shift}, "p", function() awful.client.swap.global_bydirection("up") end),
    awful.key({key.mod, key.shift}, "n", function() awful.client.swap.global_bydirection("down") end),
    awful.key({key.mod, key.shift}, "b", function() awful.client.swap.global_bydirection("left") end),
    awful.key({key.mod, key.shift}, "o", function() awful.client.swap.global_bydirection("right") end),
    awful.key({key.mod, key.ctrl}, "b", function() awful.tag.incmwfact(-0.02, nil) end),
    awful.key({key.mod, key.ctrl}, "o", function() awful.tag.incmwfact(0.02, nil) end)
  )

  for i = 1, #tags do
    keys.global = gears.table.join(keys.global, awful.key({key.mod}, tostring(i), function()
                                       tags[i]:view_only()
                                       current_screen = tags[i].screen
                                       tagModuleUpdate()
    end))
  end
#+END_SRC
Client keys
#+BEGIN_SRC lua
  keys.client = gears.table.join(
    awful.key({key.mod, key.shift}, "q", function(c) c:kill() end),
    awful.key({key.mod}, "f", function(c) c.fullscreen = not c.fullscreen end),
    awful.key({key.mod, key.ctrl}, "p", function(c) c.incwfact(-0.02) end),
    awful.key({key.mod, key.ctrl}, "n", function(c) c.incwfact(0.02) end),
    awful.key({key.mod}, "s", function(c) 
        c.floating = not c.floating
        if c.floating then
          c.ontop = true
        else
          c.ontop = false
        end
    end)
  )

  buttons.client = gears.table.join(
    awful.button({ }, 1, function (c)
        c:emit_signal("request::activate", "mouse_click", {raise = true})
    end),
    awful.button({ key.mod }, 1, function (c)
        c:emit_signal("request::activate", "mouse_click", {raise = true})
        awful.mouse.client.move(c)
    end),
    awful.button({ key.mod }, 3, function (c)
        c:emit_signal("request::activate", "mouse_click", {raise = true})
        awful.mouse.client.resize(c)
    end)
  )
  for i = 1, #tags do
    keys.client = gears.table.join(keys.client, awful.key({key.mod, key.shift}, tostring(i), function(c)
                                       c:move_to_tag(tags[i])
                                       tagModuleUpdate()
    end))
  end
#+END_SRC
Set global keys
#+BEGIN_SRC lua
  root.keys(keys.global)
#+END_SRC
* Client
** Rules
#+BEGIN_SRC lua
  awful.rules.rules = {
    {
      rule = {},
      properties = {
        size_hints_honor = false,
        focus = true,
        buttons = buttons.client,
        keys = keys.client,
        titlebars_enabled = true,
        screen = function()
          return current_screen
        end
      }
    }
  }
#+END_SRC
** Management
#+BEGIN_SRC lua
  client.connect_signal("manage", function(c)
        c.shape = function(cr, w, h)
          if (awful.screen.focused().selected_tag.gap == 0 and not c.floating) or c.fullscreen then
            return gears.shape.rectangle(cr, w, h)
          else
            return gears.shape.rounded_rect(cr, w, h, beautiful.corner_radius)
          end
        end
  end)

  client.connect_signal("mouse::enter", function(c)
        c:emit_signal("request::activate", "mouse_enter", {raise = false})
  end)
#+END_SRC
* Run startup script
#+BEGIN_SRC lua
  awful.spawn.with_shell("bash " .. os.getenv("HOME") .. "/.config/awesome/config.bash")
#+END_SRC
* Handle errors
#+BEGIN_SRC lua
  if awesome.startup_errors then
      naughty.notify({ preset = naughty.config.presets.critical,
                       title = "Oops, there were errors during startup!",
                       text = awesome.startup_errors })
  end
#+END_SRC
* Bash script to execute at startup
#+BEGIN_SRC bash
  find ~/wallpapers/ -type f | shuf -n 1 | xargs feh --bg-fill
  killall compton
  compton & disown
  xrdb ~/.Xresources
#+END_SRC
